package com.kxmall.huishou.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.kxmall.categorize.domain.HsWasteCategorize;
import com.kxmall.categorize.domain.vo.HsWasteCategorizeVo;
import com.kxmall.categorize.service.IHsWasteCategorizeService;
import com.kxmall.common.core.domain.BaseEntity;
import com.kxmall.common.core.page.TableDataInfo;
import com.kxmall.common.core.domain.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.kxmall.common.exception.ServiceException;
import com.kxmall.common.utils.StringUtils;
import com.kxmall.count.countParam.RecoverParam;
import com.kxmall.count.countVO.RecoveryChartVO;
import com.kxmall.huishou.domain.HsAppointmentOrder;
import com.kxmall.huishou.domain.bo.HsUserWasteBo;
import com.kxmall.huishou.domain.vo.HsAppointmentOrderVo;
import com.kxmall.huishou.domain.vo.HsUserWasteVo;
import com.kxmall.huishou.service.IHsUserWasteService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import com.kxmall.huishou.domain.bo.HsSettlementOrderBo;
import com.kxmall.huishou.domain.vo.HsSettlementOrderVo;
import com.kxmall.huishou.domain.HsSettlementOrder;
import com.kxmall.huishou.mapper.HsSettlementOrderMapper;
import com.kxmall.huishou.service.IHsSettlementOrderService;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;

/**
 * 回收结算订单信息Service业务层处理
 *
 * @author kxmall
 * @date 2023-11-24
 */
@RequiredArgsConstructor
@Service
public class HsSettlementOrderServiceImpl implements IHsSettlementOrderService {

    private final HsSettlementOrderMapper baseMapper;

    private final IHsWasteCategorizeService iHsWasteCategorizeService;

    private final IHsUserWasteService iHsUserWasteService;

    /**
     * 查询回收结算订单信息
     */
    @Override
    public HsSettlementOrderVo queryById(Long id){
        return baseMapper.selectVoById(id);
    }

    /**
     * 查询回收结算订单信息列表
     */
    @Override
    public TableDataInfo<HsSettlementOrderVo> queryPageList(HsSettlementOrderBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<HsSettlementOrder> lqw = buildQueryWrapper(bo);
        Page<HsSettlementOrderVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询回收结算订单信息列表
     */
    @Override
    public List<HsSettlementOrderVo> queryList(HsSettlementOrderBo bo) {
        LambdaQueryWrapper<HsSettlementOrder> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<HsSettlementOrder> buildQueryWrapper(HsSettlementOrderBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<HsSettlementOrder> lqw = Wrappers.lambdaQuery();
        lqw.eq(StringUtils.isNotBlank(bo.getOrderNo()), HsSettlementOrder::getOrderNo, bo.getOrderNo());
        lqw.eq(bo.getAppointOrderId() != null, HsSettlementOrder::getAppointOrderId, bo.getAppointOrderId());
        lqw.eq(bo.getUserId() != null, HsSettlementOrder::getUserId, bo.getUserId());
        lqw.eq(bo.getRiderId() != null, HsSettlementOrder::getRiderId, bo.getRiderId());
        lqw.eq(bo.getStatus() != null, HsSettlementOrder::getStatus, bo.getStatus());
        lqw.eq(bo.getLinkType() != null, HsSettlementOrder::getLinkType, bo.getLinkType());
        lqw.gt(bo.getQueryTime() != null,HsSettlementOrder::getCreateTime, bo.getQueryTime());
        lqw.orderByDesc(HsSettlementOrder::getCreateTime);
        return lqw;
    }

    /**
     * 新增回收结算订单信息
     */
    @Transactional(readOnly = false, rollbackFor = Exception.class)
    @Override
    public Boolean insertByBo(HsSettlementOrderBo bo) {
        HsSettlementOrder add = BeanUtil.toBean(bo, HsSettlementOrder.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }

        if(bo.getHsUserWasteBoList() != null){

            BigDecimal exceptWeight = BigDecimal.ZERO;
            BigDecimal exceptAmount = BigDecimal.ZERO;

            for(HsUserWasteBo hsUserWasteBo : bo.getHsUserWasteBoList()){
                hsUserWasteBo.setOrderType(1l);
                hsUserWasteBo.setOrderId(bo.getId());
                HsWasteCategorizeVo hsWasteCategorizeVo = iHsWasteCategorizeService.queryById(hsUserWasteBo.getCategorizeId());
                if(hsWasteCategorizeVo == null){
                    throw new RuntimeException("HsWasteCategorizeVo is not exit");
                }
                if(StringUtils.isEmpty(hsUserWasteBo.getImgUrl())){
//                    throw new ServiceException("请上传回收废品图片");
                }
                hsUserWasteBo.setCategorizeName(hsWasteCategorizeVo.getName());
//                hsUserWasteBo.setPrice(hsWasteCategorizeVo.getPrice());
                exceptWeight = exceptWeight.add(hsUserWasteBo.getWeight());
                exceptAmount = exceptAmount.add(hsUserWasteBo.getAmount());
            }

            if(add.getAmountTal().compareTo(exceptAmount) != 0 || add.getWeightTal().compareTo(exceptWeight) != 0){
                add.setAmountTal(exceptAmount);
                add.setWeightTal(exceptWeight);
                baseMapper.updateById(add);
            }

            iHsUserWasteService.insertOrUpdateByBoList(bo.getHsUserWasteBoList());
        }else {
            throw new ServiceException("结算订单废品信息不能为空");
        }

        return flag;
    }

    /**
     * 修改回收结算订单信息
     */
    @Override
    public Boolean updateByBo(HsSettlementOrderBo bo) {
        HsSettlementOrder update = BeanUtil.toBean(bo, HsSettlementOrder.class);
        validEntityBeforeSave(update);

        if(bo.getHsUserWasteBoList() != null ){
            for(HsUserWasteBo hsUserWasteBo : bo.getHsUserWasteBoList()){
                hsUserWasteBo.setOrderType(1l);
                hsUserWasteBo.setOrderId(bo.getId());
                HsWasteCategorizeVo hsWasteCategorizeVo = iHsWasteCategorizeService.queryById(hsUserWasteBo.getCategorizeId());
                if(hsWasteCategorizeVo == null){
                    continue;
                }
                hsUserWasteBo.setCategorizeName(hsWasteCategorizeVo.getName());
//                hsUserWasteBo.setPrice(hsWasteCategorizeVo.getPrice());
            }

            iHsUserWasteService.insertOrUpdateByBoList(bo.getHsUserWasteBoList());
        }else {
            throw new ServiceException("结算订单废品信息不能为空");
        }

        return baseMapper.updateById(update) > 0;
    }

    /**
     * 修改回收结算订单状态
     */
    @Override
    public Boolean updateById(HsSettlementOrder order) {
        if(order == null || order.getId() == null || order.getStatus() == null){
            return false;
        }

        return baseMapper.update(order, new QueryWrapper<HsSettlementOrder>().eq("id",order.getId())) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(HsSettlementOrder entity){
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除回收结算订单信息
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        for (Long id : ids) {
            // 在这里你可以对每个 id 进行需要的操作
            HsSettlementOrderVo hsSettlementOrderVo = baseMapper.selectVoById(id);
            if(hsSettlementOrderVo.getStatus() == 0){
                throw new ServiceException("订单处于结算中状态不可删除");
            }
            if(hsSettlementOrderVo.getStatus() == 1){
                throw new ServiceException("订单处于未支付状态不可删除");
            }
            if(hsSettlementOrderVo.getStatus() == 3){
                throw new ServiceException("订单处于待确认状态不可删除");
            }
            iHsUserWasteService.deletaByOrderId(hsSettlementOrderVo.getId());
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    @Override
    public Double sumAmountByRiderId(Long riderId, Date startTime, Date endTime){
        return baseMapper.sumAmountByRiderId(riderId, startTime, endTime);
    }

    @Override
    public List<RecoveryChartVO> getRecoveryChartVOList(RecoverParam recoverParam) {
        List<RecoveryChartVO> chartVOArrayList = new ArrayList<>();

        LambdaQueryWrapper<HsSettlementOrder> q = new LambdaQueryWrapper<>();
        q.eq(HsSettlementOrder::getStatus,4);
        if(recoverParam.getType() == 1 || recoverParam.getType() == 2 || recoverParam.getType() == 5){
            chartVOArrayList = typeDay(recoverParam,q);
        }else if(recoverParam.getType() == 3){
            chartVOArrayList = typeWeek(recoverParam,q);
        }else if(recoverParam.getType() == 4){
            chartVOArrayList = typeMonth(recoverParam,q);
        }
        return chartVOArrayList;
    }

    @Override
    public List<RecoveryChartVO> getChartVOListSeven() {
        List<RecoveryChartVO> chartVOArrayList = new ArrayList<>();
        LocalDate now = LocalDate.now();
        LocalDate date = now.minusDays(6);

        LambdaQueryWrapper<HsSettlementOrder> q = new LambdaQueryWrapper<>();
        q.eq(HsSettlementOrder::getStatus,4);
        q.ge(HsSettlementOrder::getCreateTime,date);
        List<HsSettlementOrderVo> hsSettlementOrderVos = baseMapper.selectVoList(q);
        for (int i = 6; i >= 0; i--) {
            RecoveryChartVO chartVO = new RecoveryChartVO();
            chartVO.setName(String.valueOf(now.minusDays(i)));
            chartVO.setUnit("吨"); // 设置单位为吨

            // 使用临时变量进行数值累加
            BigDecimal totalWeight = BigDecimal.ZERO;

            for (HsSettlementOrderVo hsSettlementOrderVo : hsSettlementOrderVos) {
                LocalDate createTime = LocalDateTime
                        .ofInstant(hsSettlementOrderVo.getCreateTime().toInstant(), ZoneId.systemDefault())
                        .toLocalDate();
                if (createTime.compareTo(now.minusDays(i)) == 0) {
                    if(hsSettlementOrderVo.getWeightTal() != null){
                        totalWeight = totalWeight.add(hsSettlementOrderVo.getWeightTal());
                    }
                }
            }

            // 设置原始数值
            chartVO.setValueNumber(totalWeight.toString());

            // 格式化最终值（包含单位）
            chartVO.setValue(formatWeightValueWithUnit(totalWeight));

            // 设置最终单位
            chartVO.setUnit(getFinalWeightUnit(totalWeight));

            chartVOArrayList.add(chartVO);
        }
        return chartVOArrayList;
    }

    //获取天类型
    private List<RecoveryChartVO> typeDay(RecoverParam recoverParam, LambdaQueryWrapper<HsSettlementOrder> q){
        LocalDate now = LocalDate.now();
        LocalDate date = now.minusDays(1);
        List<RecoveryChartVO> chartVOArrayList = new ArrayList<>();
        if(recoverParam.getType() == 1){
            q.ge(HsSettlementOrder::getCreateTime,now);
        }else if(recoverParam.getType() == 2){
            q.ge(HsSettlementOrder::getCreateTime,date);
            q.lt(HsSettlementOrder::getCreateTime,now);
        }else if(recoverParam.getType() == 5){
        q.ge(HsSettlementOrder::getCreateTime,recoverParam.getTime());
        q.lt(HsSettlementOrder::getCreateTime,recoverParam.getTime().plusDays(1));
    }
        List<HsSettlementOrderVo> hsSettlementOrderVos = baseMapper.selectVoList(q);
        for (int i = 1; i <=24; i++) {
            RecoveryChartVO chartVO = new RecoveryChartVO();
            chartVO.setName(String.valueOf(i));
            chartVO.setUnit("吨"); // 设置单位为吨

            // 使用临时变量进行数值累加
            BigDecimal totalWeight = BigDecimal.ZERO;

            for (HsSettlementOrderVo hsSettlementOrderVo : hsSettlementOrderVos) {
                int hours = hsSettlementOrderVo.getCreateTime().getHours();
                if(hours == i){
                    if(hsSettlementOrderVo.getWeightTal() != null){
                        totalWeight = totalWeight.add(hsSettlementOrderVo.getWeightTal());
                    }
                }
            }

            // 设置原始数值
            chartVO.setValueNumber(totalWeight.toString());

            // 格式化最终值（包含单位）
            chartVO.setValue(formatWeightValueWithUnit(totalWeight));

            // 设置最终单位
            chartVO.setUnit(getFinalWeightUnit(totalWeight));

            chartVOArrayList.add(chartVO);
        }
        return chartVOArrayList;
    }
    //获取周类型
    private List<RecoveryChartVO> typeWeek(RecoverParam recoverParam, LambdaQueryWrapper<HsSettlementOrder> q){
        List<RecoveryChartVO> chartVOArrayList = new ArrayList<>();
        LocalDate now = LocalDate.now();
        LocalDate startOfWeek = now.with(DayOfWeek.MONDAY);
        q.ge(HsSettlementOrder::getCreateTime,startOfWeek);
        List<HsSettlementOrderVo> hsSettlementOrderVos = baseMapper.selectVoList(q);
        for (int i = 1; i <= 7; i++) {
            RecoveryChartVO chartVO = new RecoveryChartVO();
            chartVO.setName(String.valueOf(i));
            chartVO.setUnit("吨"); // 设置单位为吨

            // 使用临时变量进行数值累加
            BigDecimal totalWeight = BigDecimal.ZERO;

            for (HsSettlementOrderVo hsSettlementOrderVo : hsSettlementOrderVos) {
                int value = hsSettlementOrderVo.getCreateTime().getDay();
                if (value == i) {
                    if(hsSettlementOrderVo.getWeightTal() != null){
                        totalWeight = totalWeight.add(hsSettlementOrderVo.getWeightTal());
                    }
                }
            }

            // 设置原始数值
            chartVO.setValueNumber(totalWeight.toString());

            // 格式化最终值（包含单位）
            chartVO.setValue(formatWeightValueWithUnit(totalWeight));

            // 设置最终单位
            chartVO.setUnit(getFinalWeightUnit(totalWeight));

            chartVOArrayList.add(chartVO);
        }
        return chartVOArrayList;
    }
    //获取月类型
    private List<RecoveryChartVO> typeMonth(RecoverParam recoverParam, LambdaQueryWrapper<HsSettlementOrder> q){
        List<RecoveryChartVO> chartVOArrayList = new ArrayList<>();
        LocalDate now = LocalDate.now();
        LocalDate firstDayOfMonth  = now.withDayOfMonth(1);
        q.ge(HsSettlementOrder::getCreateTime,firstDayOfMonth );
        List<HsSettlementOrderVo> hsSettlementOrderVos = baseMapper.selectVoList(q);
        for (int i = 1; i <= 30; i++) {
            RecoveryChartVO chartVO = new RecoveryChartVO();
            chartVO.setName(String.valueOf(i));
            chartVO.setUnit("吨"); // 设置单位为吨

            // 使用临时变量进行数值累加
            BigDecimal totalWeight = BigDecimal.ZERO;

            for (HsSettlementOrderVo hsSettlementOrderVo : hsSettlementOrderVos) {
                int value = hsSettlementOrderVo.getCreateTime().getDate();
                if (value == i) {
                    if(hsSettlementOrderVo.getWeightTal() != null){
                        totalWeight = totalWeight.add(hsSettlementOrderVo.getWeightTal());
                    }
                }
            }

            // 设置原始数值
            chartVO.setValueNumber(totalWeight.toString());

            // 格式化最终值（包含单位）
            chartVO.setValue(formatWeightValueWithUnit(totalWeight));

            // 设置最终单位
            chartVO.setUnit(getFinalWeightUnit(totalWeight));

            chartVOArrayList.add(chartVO);
        }
        return chartVOArrayList;
    }

    /**
     * 格式化重量数值并添加单位
     * @param weight 重量值（吨）
     * @return 格式化后的字符串（包含单位）
     */
    private String formatWeightValueWithUnit(BigDecimal weight) {
        if (weight == null) {
            weight = BigDecimal.ZERO;
        }

        // 保留2位小数
        BigDecimal formattedWeight = weight.setScale(2, RoundingMode.HALF_UP);

        // 如果大于等于1000吨，转换为千吨
        if (formattedWeight.compareTo(new BigDecimal("1000")) >= 0) {
            BigDecimal weightInKiloTons = formattedWeight.divide(new BigDecimal("1000"), 2, RoundingMode.HALF_UP);
            return weightInKiloTons.toString() + "千吨";
        } else {
            return formattedWeight.toString() + "吨";
        }
    }

    /**
     * 获取最终重量单位
     * @param weight 重量值（吨）
     * @return 最终单位
     */
    private String getFinalWeightUnit(BigDecimal weight) {
        if (weight == null) {
            return "吨";
        }

        BigDecimal formattedWeight = weight.setScale(2, RoundingMode.HALF_UP);
        return formattedWeight.compareTo(new BigDecimal("1000")) >= 0 ? "千吨" : "吨";
    }

}
